
#include <BFile>
#include <BEntry>
#include <BFolder>
#include <BReadWrite>
#include <BTreeItem>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BMessageBox>
#include <BStyle>
#include <BLabel>
#include <BCursor>
#include <BHtmlWidget>
#include <BTextEdit>
#include <BApplication>

#include "TextBoard.h"
#include "YamlFormat.h"
#include "MainWindow.h"

MainWindow::MainWindow()
{
	_fileDialog = new BFileDialog(this);

	initMenuBar();

	_openButton = new BButton(_fileMenu->action("Open"));
	_saveButton = new BButton("save");
	_saveButton->setEnabled(false);
	_saveAllButton = new BButton("save-all");
	_saveAllButton->setEnabled(false);
	_removeButton = new BButton("remove");

	BHBoxLayout* toolLayout = new BHBoxLayout();
	toolLayout->addWidget(_openButton);
	toolLayout->addWidget(_saveButton);
	toolLayout->addWidget(_saveAllButton);
	toolLayout->addWidget(_removeButton);
	toolLayout->addSpring(100);

	BHBoxLayout* splitLayout = new BHBoxLayout();
	splitLayout->setSplitable(true);
	splitLayout->setSpacing(6);
	{
		_workspace = new BTreeWidget();
		_workspace->setSelectMode(Select_Single);

		_tabWidget = new BTabWidget();

		splitLayout->addWidget(_workspace);
		splitLayout->addWidget(_tabWidget, 4);
	}

	BVBoxLayout* layout = new BVBoxLayout(this);
	layout->addWidget(_menuBar, 0);
	layout->addLayout(toolLayout, 0);
	layout->addLayout(splitLayout);

	connect(_workspace, Signal_ItemDoubleClicked, &MainWindow::slotHeadItemDoubleClicked);
	connect(_workspace, Signal_ItemRightClicked, &MainWindow::slotHeadItemRightClicked);

	connect(_tabWidget, Signal_CurrentChanged, &MainWindow::slotTabCurrentChanged);
	connect(_tabWidget, Signal_TabClosing, &MainWindow::slotTabClosing);
	connect(_tabWidget, Signal_TabClicked, &MainWindow::slotTabClicked);
	connect(_tabWidget, Signal_TabRightClicked, &MainWindow::slotTabRightClicked);

	connect(_removeButton, Signal_Clicked, &MainWindow::slotRemoveButtonClicked);

	this->openHtmlFile("../../document/index.html");
}
MainWindow::~MainWindow()
{

}

void MainWindow::initMenuBar()
{
	_menuBar = new BMenuBar();
	_menuBar->setSpacing(3);

	_fileMenu = new BMenu("File");
	{
		BAction* newAction = _fileMenu->addAction("New");
		BAction* openAction = _fileMenu->addAction("Open");
		BAction* saveAction = _fileMenu->addAction("Save");
		BAction* saveAsAction = _fileMenu->addAction("Save-As");
		BAction* saveAllAction = _fileMenu->addAction("Save-All");
		BAction* closeAction = _fileMenu->addAction("Close");
		_fileMenu->addSeparator();
		BAction* quitAction = _fileMenu->addAction("Quit");
		connect(newAction, Signal_Triggered, &MainWindow::slotNewActionTriggered);
		connect(openAction, Signal_Triggered, &MainWindow::slotOpenActionTriggered);
		connect(saveAction, Signal_Triggered, &MainWindow::slotSaveActionTriggered);
		connect(saveAsAction, Signal_Triggered, &MainWindow::slotSaveAsActionTriggered);
		connect(saveAllAction, Signal_Triggered, &MainWindow::slotSaveAllActionTriggered);
		connect(closeAction, Signal_Triggered, &MainWindow::slotCloseActionTrigger);
	}

	_editMenu = new BMenu("Edit");
	_editMenu->addAction("Undo");
	_editMenu->addAction("Redo");
	_editMenu->addSeparator();
	_editMenu->addAction("Copy");
	_editMenu->addAction("Cut");
	_editMenu->addAction("Paste");
	_editMenu->addAction("Remove");

	_viewMenu = new BMenu("View");

	_toolMenu = new BMenu("Tool");

	_menuBar->addMenu(_fileMenu);
	_menuBar->addMenu(_editMenu);
	_menuBar->addMenu(_viewMenu);
	_menuBar->addMenu(_toolMenu);

	_listMenu = new BMenu(this);
	_listMenu->addAction("open");
	_listMenu->addAction("fresh");
	_listMenu->addAction("check");

	_pageMenu = new BMenu(this);
	//_pageMenu->setForm(Form_TextOnly);
	_pageMenu->addAction("open source")->setName("action-source");
	_pageMenu->addAction("show tree")->setName("action-tree");

	_tableMenu = new BMenu(this);
	_tableMenu->addAction("add row")->setName("action-add-row");
	_tableMenu->addAction("insert row")->setName("action-insert-row");
	_tableMenu->addAction("remove row")->setName("action-remove-row");
	_tableMenu->addAction("add column")->setName("action-add-column");
	_tableMenu->addAction("insert column")->setName("action-insert-column");
	_tableMenu->addAction("remove column")->setName("action-remove-column");

	_tabMenu = new BMenu(this);
	_tabMenu->addAction("Close Current Document")->setName("action-close-tab");
	_tabMenu->addAction("Close All Document")->setName("action-close-all-tab");
	_tabMenu->addAction("Close All Except Current")->setName("action-close-all-except-current");

	{
		BMenu* headMenu = new BMenu("head");
		headMenu->addAction("h1");
		headMenu->addAction("h2");
		headMenu->addAction("h3");
		headMenu->addAction("h4");
		headMenu->addAction("h5");
		headMenu->addAction("h6");

		BAction* pAction = new BAction("p");
		BAction* aAction = new BAction("a");
		BAction* textAction = new BAction("text");
		BAction* divAction = new BAction("div");
		BAction* tableAction = new BAction("table");
		BAction* imgAction = new BAction("img");

		BMenu* addMenu = new BMenu("Add");
		addMenu->setName("menu-add");
		addMenu->addMenu(headMenu);
		addMenu->addAction(pAction);
		addMenu->addAction(aAction);
		addMenu->addAction(textAction);
		addMenu->addAction(imgAction);
		addMenu->addAction(divAction);
		addMenu->addAction(tableAction);

		BMenu* prependMenu = new BMenu("Prepend");
		prependMenu->setName("menu-prepend");
		prependMenu->addMenu(headMenu);
		prependMenu->addAction(pAction);
		prependMenu->addAction(aAction);
		prependMenu->addAction(textAction);
		prependMenu->addAction(imgAction);
		prependMenu->addAction(divAction);
		prependMenu->addAction(tableAction);

		BMenu* appendMenu = new BMenu("Append");
		appendMenu->setName("menu-append");
		appendMenu->addMenu(headMenu);
		appendMenu->addAction(pAction);
		appendMenu->addAction(aAction);
		appendMenu->addAction(textAction);
		appendMenu->addAction(imgAction);
		appendMenu->addAction(divAction);
		appendMenu->addAction(tableAction);

		_pageMenu->addMenu(addMenu);
		_pageMenu->addMenu(prependMenu);
		_pageMenu->addMenu(appendMenu);

		connect(addMenu, Signal_Triggered, &MainWindow::slotMenuAddTrigger);
		connect(prependMenu, Signal_Triggered, &MainWindow::slotMenuPrependTrigger);
		connect(appendMenu, Signal_Triggered, &MainWindow::slotMenuAppendTrigger);
	}

	connect(_pageMenu, Signal_Triggered, &MainWindow::slotPageMenuTrigger);
	connect(_tableMenu, Signal_Triggered, &MainWindow::slotTableMenuTrigger);
	connect(_tabMenu, Signal_Triggered, &MainWindow::slotTabMenuTrigger);

}
bool MainWindow::openHtmlFile(const BString& fileName)
{
	BString title = fileName.name();
	title -= ".html";

	if (_tabWidget->setCurrentWidget(title))
	{
		return true;
	}

	BHolder<BHtmlWidget> htmlWidget = new BHtmlWidget();
	if (!htmlWidget->load(fileName))
		return false;

	BHtmlItem* body = htmlWidget->body();

	htmlWidget->setName(fileName);
	htmlWidget->setTitle(title);
	htmlWidget->setTitleIcon(_htmlIcon);

	_tabWidget->addTab(htmlWidget, true);
	_tabWidget->setCurrentWidget(htmlWidget);
	connect(htmlWidget, Signal_ItemClicked, &MainWindow::slotHtmlItemClicked);
	connect(htmlWidget, Signal_ItemRightClicked, &MainWindow::slotHtmlItemRightClicked);
	connect(htmlWidget, Signal_ItemChanged, &MainWindow::slotHtmlItemChanged);
	return true;
}
void MainWindow::signTitleChanged(BWidget* widget, bool changed)
{
	const BString& title = widget->title();
	if (changed)
	{
		if (title.first() != '*')
		{
			BString newTitle("*");
			newTitle << title;
			widget->setTitle(newTitle);
		}
	}
	else
	{
		if (title.first() == '*')
		{
			BString newTitle = title;
			newTitle.remove('*');
			widget->setTitle(newTitle);
		}
	}
}

void MainWindow::slotHeadItemRightClicked(BObject* object, const BValue& value)
{
	BTreeItem* item = value;
	if (!item)
		return;
	const BPoint& point = BCursor::GetPos();
	BPoint pos = point - this->pos();
	_listMenu->setPos(pos);
	_listMenu->popup();
}
void MainWindow::slotHeadItemDoubleClicked(BObject* object, const BValue& value)
{
	BTreeItem* item = value;
	if (!item)
		return;
	const HeadInfo* info = item->asset();
	if(info && info->htmlEntry)
	{
		const BString& htmlName = info->htmlEntry->path();
	}
}

void MainWindow::slotTabCurrentChanged(BObject* object, const BValue& value)
{
	_removeButton->setEnabled(true);
}
void MainWindow::slotTabClicked(BObject* object, BValue& value)
{
	BWidget* widget = value;
	if (widget)
	{
		const BString& title = widget->title();
	}
}
void MainWindow::slotTabRightClicked(BObject* object, BValue& value)
{
	BWidget* widget = value;
	const BPoint& point = BCursor::GetPos();
	BPoint pos = point - this->pos();
	_tabMenu->setPos(pos);
	_tabMenu->popup();
}

void MainWindow::slotTabClosing(BObject* object, BValue& value)
{
	BHtmlWidget* htmlWidget = value;
	if (htmlWidget && htmlWidget->title().first() == '*')
	{
		Button btn = BMessageBox::Question(this, "Close Html", "Do you want close the html document ?");
		if (btn == Button_No)
			value = 0;
	}
}
void MainWindow::slotRemoveButtonClicked(BObject* object, const BValue& value)
{

}

void MainWindow::slotNewActionTriggered(BObject* object, const BValue& value)
{

}
void MainWindow::slotOpenActionTriggered(BObject* object, const BValue& value)
{
	BString fileName = BFileDialog::OpenFile(0, "Open file");
	if (fileName.empty())
		return;
	BString text;
	if (!BFile::Load(fileName, text))
	{
		BString text("Open file ");
		text << fileName + " Failed.";
		Button result = BMessageBox::Warning(this, "Question", text);
		return;
	}
	TextBoard* textEdit = new TextBoard();
	if (fileName.endWith(".yaml"))
	{
		textEdit->setFormat(new YamlFormat());
	}
	if (fileName.endWith(".html"))
	{

	}
	textEdit->setText(text);
	_tabWidget->addTab(textEdit);
	_tabWidget->setCurrentWidget(textEdit);

}
void MainWindow::slotSaveActionTriggered(BObject* object, const BValue& value)
{
	BHtmlWidget* htmlWidget = dynamic_cast<BHtmlWidget*>(_tabWidget->currentWidget());
	if (htmlWidget)
	{
		if (!htmlWidget->save(htmlWidget->name()))
		{
			BString text("Save html file ");
			text << htmlWidget->name() << " Failed.";
			BMessageBox::Critical(this, "Critical", text);
		}
		else
		{
			signTitleChanged(htmlWidget, false);
		}
	}
}
void MainWindow::slotSaveAsActionTriggered(BObject* object, const BValue& value)
{

}
void MainWindow::slotSaveAllActionTriggered()
{
	for (int i = 0; i < _tabWidget->tabCount(); i++)
	{
		BWidget* tab = _tabWidget->tab(i);
		BHtmlWidget* htmlWidget = dynamic_cast<BHtmlWidget*>(tab);
		if (!htmlWidget || htmlWidget->title().first() != '*')
			continue;
		if (htmlWidget->save(htmlWidget->name()))
			signTitleChanged(htmlWidget, false);
	}
}
void MainWindow::slotCloseActionTrigger(BObject* object, const BValue& value)
{
	BTextEdit* textEdit = (BTextEdit*)_tabWidget->currentWidget();
	const BString& fileName = textEdit->property("fileName");
	if (!BFile::Exist(fileName))
	{
		BString text;
		text << fileName << "\nfile is not exist, do you want to save ?";
		if (Button_Yes == BMessageBox::Question(this, "Question", text))
		{
			BFile::Save(fileName, textEdit->text());
		}
	}
	_tabWidget->removeTab(textEdit);
}
void MainWindow::slotPageMenuTrigger(BObject* object, const BValue& value)
{
	BAction* action = value;
	if (!action)
		return;
	if (action->name() == "action-source")
	{
		BHtmlWidget* html = dynamic_cast<BHtmlWidget*>(_tabWidget->currentWidget());
		if (!html)
			return;
		BTextEdit* textEdit = new BTextEdit();
		textEdit->setTitle(html->title() + ".html");
		textEdit->setName(html->name());
		textEdit->setTitleIcon(_textIcon);
		textEdit->setReadOnly(true);
		textEdit->load(html->name());

		_tabWidget->addTab(textEdit, true);
		_tabWidget->setCurrentWidget(textEdit);
		return;
	}
	if (action->name() == "action-tree")
	{
		BHtmlWidget* html = dynamic_cast<BHtmlWidget*>(_tabWidget->currentWidget());
		if (!html)
			return;
		BXmlNode* body = html->body();
		BXmlNode* root = body->root();

	}
}
void MainWindow::slotTableMenuTrigger(BObject* object, const BValue& value)
{
	BAction* action = value;
	if (!action)
		return;
	BHtmlWidget* htmlWidget = dynamic_cast<BHtmlWidget*>(_tabWidget->currentWidget());
	if (!htmlWidget)
		return;
	BHtmlItem* item = htmlWidget->selectedItem();
	if (!item)
		return;
	if (item->name() == "td")
	{
		BHtmlItem* table = item->parent("table");
		int row = 0;
		int column = 0;
		int columnCount = 0;
		for (int r = 0; r < table->childCount(); r++)
		{
			BHtmlItem* rowItem = table->child(r);
			if (columnCount < rowItem->childCount())
				columnCount = rowItem->childCount();
			for (int c = 0; c < rowItem->childCount(); c++)
			{
				BHtmlItem* tdItem = rowItem->child(c);
				if (tdItem == item)
				{
					row = r;
					column = c;
					break;
				}
			}
		}
		if (action->name() == "action-add-column")
		{
			for (int r = 0; r < table->childCount(); r++)
			{
				BHtmlItem* rowItem = table->child(r);
				rowItem->addChild(new BHtmlItem("td"));
			}
			return;
		}
		if (action->name() == "action-add-row")
		{
			BHtmlItem* rowItem = new BHtmlItem("tr");
			rowItem->setFormat("\n<");
			for (int c = 0; c < columnCount; c++)
				rowItem->addChild(new BHtmlItem("td"));
			table->addChild(rowItem);
			return;
		}
	}
	if (item->name() == "table")
	{
		int columnCount = 0;
		for (int r = 0; r < item->childCount(); r++)
		{
			BHtmlItem* rowItem = item->child(r);
			if (columnCount < rowItem->childCount())
				columnCount = rowItem->childCount();
		}
	
		if (action->name() == "action-add-row")
		{
			BHtmlItem* rowItem = new BHtmlItem("tr");
			rowItem->setFormat("\n<");
			for (int c = 0; c < columnCount; c++)
				rowItem->addChild(new BHtmlItem("td"));
			item->addChild(rowItem);
			return;
		}
		if (action->name() == "action-add-column")
		{
			for (int i = 0; i < item->childCount(); i++)
			{
				BHtmlItem* rowItem = item->child(i);
				rowItem->addChild(new BHtmlItem("td"));
			}
		}
		return;
	}
}
void MainWindow::slotTabMenuTrigger(BObject* object, const BValue& value)
{
	("action-close-all-except-current");
	BAction* action = value;
	if (action->name() == "action-close-tab")
	{
		BWidget* widget = _tabWidget->currentWidget();
		_tabWidget->removeTab(widget);
		return;
	}
	if (action->name() == "action-close-all-tab")
	{
		_tabWidget->clearTabs();
	}
}

void MainWindow::slotHtmlItemClicked(BObject* object, const BValue& value)
{
	BHtmlItem* item = value;
	if (item && item->name() == 'a')
	{

	}
}
void MainWindow::slotHtmlItemRightClicked(BObject* object, const BValue& value)
{
	BHtmlWidget* htmlWidget = dynamic_cast<BHtmlWidget*>(object);
	BHtmlItem* item = value;
	const BPoint& point = BCursor::GetPos();
	BPoint pos = point - this->pos();
	_tableMenu->action("add row")->setEnabled(false);
	_tableMenu->action("insert row")->setEnabled(false);
	_tableMenu->action("remove row")->setEnabled(false);
	_tableMenu->action("add column")->setEnabled(false);
	_tableMenu->action("insert column")->setEnabled(false);
	_tableMenu->action("remove column")->setEnabled(false);
	if (item && item->name() == "table")
	{
		_tableMenu->action("add row")->setEnabled(true);
		_tableMenu->action("add column")->setEnabled(true);
		_tableMenu->setPos(pos);
		_tableMenu->popup();
	}
	else if (item && item->name() == "tr")
	{
		_tableMenu->action("add row")->setEnabled(true);
		_tableMenu->action("insert row")->setEnabled(true);
		_tableMenu->action("remove row")->setEnabled(true);
		_tableMenu->setPos(pos);
		_tableMenu->popup();
	}
	else if (item && item->name() == "td")
	{
		_tableMenu->action("add row")->setEnabled(true);
		_tableMenu->action("insert row")->setEnabled(true);
		_tableMenu->action("remove row")->setEnabled(true);
		_tableMenu->action("add column")->setEnabled(true);
		_tableMenu->action("insert column")->setEnabled(true);
		_tableMenu->action("remove column")->setEnabled(true);
		_tableMenu->setPos(pos);
		_tableMenu->popup();
	}
	else
	{
		_pageMenu->setPos(pos);
		_pageMenu->popup();
	}
}
void MainWindow::slotHtmlItemChanged(BObject* object, const BValue& value)
{
	BHtmlWidget* htmlWidget = dynamic_cast<BHtmlWidget*>(object);
	signTitleChanged(htmlWidget, true);
}

void MainWindow::slotMenuAddTrigger(BObject* object, const BValue& value)
{
	BMenu* menu = dynamic_cast<BMenu*>(object);
	if (!menu)
		return;

	BAction* action = value;
	if (!action)
		return;

	BHtmlItemHolder item = new BHtmlItem();
	const BString& text = action->text();
	if (text != "text")
		item->setName(action->text());
	if (text == "p" || text == "div" || (text.size() == 2 && text[0] == 'h'))
		item->setFormat("\n<");


}
void MainWindow::slotMenuPrependTrigger(BObject* object, const BValue& value)
{
	BMenu* menu = dynamic_cast<BMenu*>(object);
	if (!menu)
		return;

	BAction* action = value;
	if (!action)
		return;

	BHtmlItemHolder item = new BHtmlItem();
	const BString& text = action->text();
	if (text != "text")
		item->setName(action->text());
	if (text == "p" || text == "div" || (text.size() == 2 && text[0] == 'h'))
		item->setFormat("\n<");

}
void MainWindow::slotMenuAppendTrigger(BObject* object, const BValue& value)
{
	BMenu* menu = dynamic_cast<BMenu*>(object);
	if (!menu)
		return;

	BAction* action = value;
	if (!action)
		return;

	BHtmlItemHolder item = new BHtmlItem();
	const BString& text = action->text();
	if (text != "text")
		item->setName(action->text());
	if (text == "p" || text == "div" || (text.size() == 2 && text[0] == 'h'))
		item->setFormat("\n<");

}

void MainWindow::updateEvent(const BEvent& event)
{
	if (!_saveButton->enabled() && _tabWidget->tabCount())
	{
		BWidget* widget = _tabWidget->currentWidget();
		if (widget->title().contain('*'))
			_saveButton->setEnabled(true);
	}
	if (!_saveAllButton->enabled() && _saveButton->enabled())
	{
		_saveAllButton->setEnabled(true);
	}
}

void MainWindow::styleEvent(const BEvent& event)
{
	const BStyle* style = event.value();

	_removeButton->setIcon(style->icon("button-remove"));
	_htmlIcon = style->icon("html-icon");
	_textIcon = style->icon("text-edit-icon");
	_treeIcon = style->icon("xml-tree-icon");
	_normalImage = style->image("normal");
	_dirtyImage = style->image("dirty");
	_emptyImage = style->image("empty");

	for (int i = 0; i < _tabWidget->tabCount(); i++)
	{
		BWidget* widget = _tabWidget->tab(i);
		if (dynamic_cast<BHtmlWidget*>(widget))
		{
			widget->setTitleIcon(_htmlIcon);
			continue;
		}
		if (dynamic_cast<BTextEdit*>(widget))
		{
			widget->setTitleIcon(_textIcon);
			continue;
		}
	}

	for (int i = 0; i < _pageMenu->count(); i++)
	{
		BAction* action = _pageMenu->action(i);
		if (action)
		{
			action->setIcon(style->icon(action->name()));
		}
		BMenu* menu = _pageMenu->menu(i);
		if (menu)
		{
			menu->setTitleIcon(style->icon(menu->name()));
		}
	}

	for (int i = 0; i < _listMenu->count(); i++)
	{
		BAction* action = _listMenu->action(i);
		if (action)
		{
			action->setIcon(style->icon(action->text()));
		}
	}
}
